package model

import (
	"context"
	"fmt"

	"github.com/Masterminds/squirrel"
	"github.com/zeromicro/go-zero/core/stores/cache"
	"github.com/zeromicro/go-zero/core/stores/sqlx"
)

var _ SmsModel = (*customSmsModel)(nil)

type (
	// SmsModel is an interface to be customized, add more methods here,
	// and implement the added methods in customSmsModel.
	SmsModel interface {
		smsModel
		RowBuilder() squirrel.SelectBuilder
		FindLastVerifySmsByUserId(ctx context.Context, userId int64, duration int64) ([]*Sms, error)
		FindOneVerifySmsByUserId(ctx context.Context, userId int64, code string, duration int64) (*Sms, error)
		FindLastVerifySmsByPhone(ctx context.Context, phone string) (*Sms, error)
		Truncate(ctx context.Context)
	}

	customSmsModel struct {
		*defaultSmsModel
	}
)

func (m *defaultSmsModel) RowBuilder() squirrel.SelectBuilder {
	return squirrel.Select(smsRows).From(m.table)
}

// NewSmsModel returns a model for the database table.
func NewSmsModel(conn sqlx.SqlConn, c cache.CacheConf) SmsModel {
	return &customSmsModel{
		defaultSmsModel: newSmsModel(conn, c),
	}
}

func (m defaultSmsModel) FindLastVerifySmsByUserId(ctx context.Context, userId int64, duration int64) ([]*Sms, error) {
	build := m.RowBuilder()
	// TIME_TO_SEC(NOW()) - TIME_TO_SEC(create_time) <= 100
	query, values, err := build.Where("user_id = ? and TIME_TO_SEC(NOW()) - TIME_TO_SEC(create_time)<=? and valid=1", userId, duration).ToSql()
	if err != nil {
		return nil, nil
	}

	var resp []*Sms
	err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...)
	// color.Red("resp=%v", resp)
	switch err {
	case nil:
		return resp, nil
	default:
		return nil, err
	}
}

func (m defaultSmsModel) FindOneVerifySmsByUserId(ctx context.Context, userId int64, code string, duration int64) (*Sms, error) {
	build := m.RowBuilder()
	query, values, err := build.Where("user_id = ? and valid=1  and TIME_TO_SEC(NOW()) - TIME_TO_SEC(create_time)<=? and content=? ", userId, duration, code).ToSql()
	if err != nil {
		return nil, nil
	}

	var resp Sms
	err = m.QueryRowNoCacheCtx(ctx, &resp, query, values...)
	switch err {
	case nil:
		return &resp, nil
	default:
		return nil, err
	}

}

func (m defaultSmsModel) FindLastVerifySmsByPhone(ctx context.Context, phone string) (*Sms, error) {
	build := m.RowBuilder()
	// TIME_TO_SEC(NOW()) - TIME_TO_SEC(create_time) <= 100
	query, values, err := build.Where("valid=1 and phone=? order by create_time desc limit 1", phone).ToSql()
	if err != nil {
		return nil, nil
	}

	var resp Sms
	err = m.QueryRowNoCacheCtx(ctx, &resp, query, values...)
	switch err {
	case nil:
		return &resp, nil
	default:
		return nil, err
	}

}

func (m defaultSmsModel) Truncate(ctx context.Context) {
	build := m.RowBuilder()
	query, values, err := build.ToSql()
	if err == nil {
		var resp []*Sms
		err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...)
		if err == nil {
			for _, r := range resp {
				m.Delete(ctx, r.Id)
			}
			m.ExecNoCacheCtx(ctx, fmt.Sprintf("TRUNCATE %s ", m.tableName()))
		}
	}
}
